iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
Software Development

深入淺出Java 30天系列 第 28

Day 28: 不建議在Java 5之後的新程式碼使用raw type(下)

  • 分享至 

  • xImage
  •  

有了泛型之後,開發人員不用自己強制轉換型別,compiler會根據宣告的時候,型別參數的型別幫你轉,程式碼看起來比較簡潔,型別轉換也比較安全,因為compiler會幫你檢查型別對不對。

import java.util.ArrayList;
import java.util.List;

public class TestGenericsList {
    public static void main(String[] args) {
        // 宣告一個List,指定泛型類型
        List<String> list = new ArrayList<>();

        list.add("Hello");
        list.add("World");

        // 從List中取出元素時,不需要進行轉換
        for (String s : list) { 
            System.out.println(s); 
        }
    }
}

但是一開始就指定型別參數(type parameters)也有個缺點,相較於原始類型(raw types),會讓程式碼變得比較沒那麼彈性,舉例來說,今天有個水果商店賣兩種水果,一種是Apple,一種是Orange,他們都實作了Fruit,因為價格都不一樣,最後要算錢的時候,再使用sumFruitPrice加總所有水果的金額。

但因為sumFruitPrice一開始就指定了List的參數的型別,compiler檢查型別的時候發現不一樣,會跳出incompatible types這個錯誤訊息,無法彈性地接受不一樣的水果,既使AppleOrange都是實作Fruit,compiler還是會認定不合法。

import java.util.ArrayList;
import java.util.List;

public class FruitStore {
    public static void main(String[] args) {
        List<Apple> appleList = new ArrayList<>();
        Apple apple1 = new Apple(10);
        Apple apple2 = new Apple(20);
        appleList.add(apple1);
        appleList.add(apple2);

        List<Orange> orangeList = new ArrayList<>();
        Orange orange = new Orange(15);
        orangeList.add(orange);

        int sum = sumFruitPrice(appleList, 0);
        sum = sumFruitPrice(orangeList, sum);
        System.out.println("Sum of fruit prices: " + sum);
    }

    public static int sumFruitPrice(List<Fruit> fruits, int sum) {
        for (int i = 0; i < fruits.size(); i++) {
            sum += fruit.getPrice();
        }
        return sum;
    }
}

interface Fruit {
    public int getPrice();
}

class Apple implements Fruit {
    private int price;
    public Apple(int price) {
        this.price = price;
    }
    public int getPrice() {
        return this.price;
    }
}

class Orange implements Fruit {
    private int price;
    public Orange(int price) {
        this.price = price;
    }
    public int getPrice() {
        return this.price;
    }
}


為了讓泛型更彈性,難道我們只能選擇不安全的原始類型(raw types)嗎?這邊提供了另一種方式,可以安全又彈性的使用泛型,把泛型的型別參數(type parameters)設為Bounded wildcard types(ex: List<? extends Fruit>),就可以在還不知道參數型別的情況下,讓泛型類型(generic types)接受不一樣型別的參數,並且限制範圍。

上面的範例把sumFruitPrice的參數fruits做了調整之後,sumFruitPrice就可以吃進各種水果,雖然中間還是要自己做強制轉型,但是至少後面要加新的水果,sumFruitPrice不需要再做調整就可以加總水果的金額。

import java.util.ArrayList;
import java.util.List;

public class TestGenericsList {
    public static void main(String[] args) {
        // 宣告一個List,指定泛型類型
        List<Apple> appleList = new ArrayList<>();
        Apple apple1 = new Apple(10);
        Apple apple2 = new Apple(20);
        appleList.add(apple1);
        appleList.add(apple2);

        List<Orange> orangeList = new ArrayList<>();
        Orange orange = new Orange(15);
        orangeList.add(orange);

        int sum = sumFruitPrice(appleList, 0);
        sum = sumFruitPrice(orangeList, sum);
        System.out.println("Sum of fruit prices: " + sum);
    }

    public static int sumFruitPrice(List<? extends Fruit> fruits, int sum) {
        for (int i = 0; i < fruits.size(); i++) {
            Fruit fruit = (Fruit) fruits.get(i);
            sum += fruit.getPrice();
        }
        return sum;
    }
}

interface Fruit {
    public int getPrice();
}

class Apple implements Fruit {
    private int price;
    public Apple(int price) {
        this.price = price;
    }
    public int getPrice() {
        return this.price;
    }
}

class Orange implements Fruit {
    private int price;
    public Orange(int price) {
        this.price = price;
    }
    public int getPrice() {
        return this.price;
    }
}

Bounded wildcard types這個方法比起原始類型(raw types)更安全的地方在於,可以讓compiler先檢查是否有不合法的型別參數(type parameters),如果有就先跳出錯誤訊息(incompatible types),不會等到runtime才發現。

List<Integer> bananaList = new ArrayList<>();
Integer banana = Integer.valueOf(14);
bananaList.add(banana);
sum = sumFruitPrice(bananaList, sum);

參考資料:


上一篇
Day 27: 不建議在Java 5之後的新程式碼使用raw type(上)
下一篇
Day 29: 優先使用list而不是array(上)
系列文
深入淺出Java 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言